package com.zty.config;

import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

/**
 * @Author ZTY
 * @Description
 * @Date 14:54 2023-12-25
 **/

@Component
@Slf4j
public class RestTemplateLoggingInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest httpRequest,
                                        byte[] body,
                                        ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
        //  提取请求信息和返回值信息
        ClientHttpResponse response = clientHttpRequestExecution.execute(httpRequest, body);

        RequestInfo requestInfo = extractRequest(httpRequest, body);
        ResponseInfo responseInfo = extractResponse(response);

        log.info("call url:{},method:{},request:{},response:{}",
                requestInfo.url,
                requestInfo.method,
                requestInfo,
                responseInfo);

        return response.getStatusCode().isError()?null:response;
    }

    /**
     * 我要拿到请求的body，url，method，headers
     * @param httpRequest
     * @param body
     * @return
     */
    private RequestInfo extractRequest(HttpRequest httpRequest, byte[] body){
        RequestInfo requestInfo = new RequestInfo();
        return requestInfo.setUrl(httpRequest.getURI().toString())
                .setMethod(httpRequest.getMethodValue())
                .setHeaders(httpRequest.getHeaders().toString())
                .setBody(body.toString());

    }

    /**
     * 执行完后，要从response中提取出状态码，文字信息，headers，body
     * @param response
     * @return
     */
    private ResponseInfo extractResponse(ClientHttpResponse response) throws IOException {
        ResponseInfo responseInfo = new ResponseInfo();
        responseInfo.setStatusCode(response.getStatusCode().value())
                .setStatusText(response.getStatusText())
                .setHeaders(response.getHeaders().toString());

        //  提取body
        //  输入流只能够读一次
        InputStream inputStream = response.getBody();
        //  这样即可实现多次读取
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));

        StringBuilder builder = new StringBuilder();
        String line;

        while ((line = bufferedReader.readLine()) != null){
            builder.append(line);
            builder.append("\n");
        }

        responseInfo.setBody(builder.toString());
        return responseInfo;
    }

    @Data
    @Accessors(chain = true)
    private static class RequestInfo{
        private String url;
        private String method;
        private String headers;
        //  为了方便打印，直接将body设为String类型
        private String body;
    }

    @Data
    @Accessors(chain = true)
    private static class ResponseInfo{
        private Integer statusCode;
        private String statusText;
        private String headers;
        //  为了方便打印，直接将body设为String类型
        private String body;
    }

}
